#lang racket
(provide constant? atom? variable?  unaire? binaire? sym->fn ¬ ∧ ∨ → ☀ pr)

(define constant?
  (λ (e) (or (eq? e #t) (eq? e #f))))

(define atom?
  (λ (e) (or (constant? e) (symbol? e))))

(define operator? 
  (λ (x) (member x '(¬ ∧ ∨ → ☀))))

(define variable? 
  (λ (x) (and (symbol? x) (not (operator? x)))))

(define unaire? 
  (λ (e)
    (eq? e '¬)))

(define binaire?
  (λ (e)
     (or (eq? e '→)(eq? e '☀))))


(define sym->fn
  ;; on peut assumer que ¬ a toujours la priorité la plus basse
  (λ (symb)
    (case symb
      [(¬) ¬]
      [(∧) ∧]
      [(∨) ∨]
      [(→) →]
      [(☀) ☀])))

(define  ¬
  (λ (e)
    (not e)))

(define  ∧
  (λ e
    (if (null? e)
        #t
        (and (car e) (apply ∧ (cdr e))))))

(define  ∨
  (λ e
    (cond [(null? e)
           #f]
          [(car e) 
           #t]
          [else
           (apply ∨ (cdr e))])))

(define →
  (λ e (∨ (¬ (car e)) 
          (cadr e))))

(define ☀ ; ou exclusif
  (λ e (∨ (∧ (car e) (¬ (cadr e))) (∧ (¬ (car e)) (cadr e)))))

(define pr
  ;; on peut assumer que ¬ a toujours la priorité la plus basse
  (λ (op)
    (case op
      [(¬) 1]
      [(∧) 2]
      [(∨) 3]
      [(☀) 3]
      [(→) 4])))

